package com.web.exiaodao.remote.service.impl;

import com.alibaba.fastjson.JSON;
import com.google.common.base.Function;
import com.web.exiaodao.business.constant.JConstant;
import com.web.exiaodao.business.entity.*;
import com.web.exiaodao.business.repository.*;
import com.web.exiaodao.remote.service.ApiCommentService;
import com.web.exiaodao.remote.service.ApiOrderDetailService;
import com.web.exiaodao.remote.service.ApiOrderService;
import com.web.exiaodao.remote.vo.CommentVo;
import com.web.exiaodao.remote.vo.OrderVo;
import com.web.exiaodao.remote.vo.UserVo;
import com.web.webstart.base.constant.XaConstant;
import com.web.webstart.base.exception.BusinessException;
import com.web.webstart.base.exception.ValidationException;
import com.web.webstart.base.service.impl.BaseService;
import com.web.webstart.base.util.DateUtils;
import com.web.webstart.base.util.ReflectionUtils;
import com.web.webstart.base.util.result.XaResult;
import com.web.webstart.base.util.XaUtil;
import com.web.webstart.base.util.jpa.DynamicSpecifications;
import com.web.webstart.base.util.jpa.MyPage;
import com.web.webstart.base.util.jpa.SearchFilter;
import com.web.webstart.base.util.jpa.SearchFilter.Operator;
import com.web.webstart.base.util.jpa.WebUitl;
import org.apache.commons.lang.BooleanUtils;
import org.apache.commons.lang.math.NumberUtils;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;

/**
 * @author: zhangl
 * @times: 2016-11-02 15:58:46
 * 类的说明：前端APIComment接口实现类
 **/
@Service("ApiCommentService")
@Transactional(readOnly = false)
public class ApiCommentServiceImpl extends BaseService<Comment> implements ApiCommentService {

    private static final Logger LOGGER = Logger.getLogger(ApiCommentServiceImpl.class);

    @Autowired
    UserRepository userRepository;
    @Autowired
    CommentRepository commentRepository;

    @Autowired
    ApiOrderService orderService;
    @Autowired
    ApiOrderDetailService orderDetailService;
    @Autowired
    OrderDetailRepository orderDetailRepository;
    @Autowired
    OrderRepository orderRepository;

    @Autowired
    ServiceCommonRepository serviceCommonRepository;
    @Autowired
    ServiceDomesticNursingRepository serviceDomesticNursingRepository;
    @Autowired
    ServiceNurseTrainingRepository nurseTrainingRepository;
    @Autowired
    VSDCRepository vsdcRepository;
    @Autowired
    InstitutionRepository institutionRepository;
    @Autowired
    InsHotelRoomsTableRepository insHotelRoomsTableRepository;
    @Autowired
    BannerRepository bannerRepository;
    @Autowired
    ShopRepository shopRepository;
    @Autowired
    ExchangeProductsRepository exchangeProductsRepository;
    @Autowired
    ArtInformationRepository artInformationRepository;//作者
    @Autowired
    AutherWorksTableRepository autherWorksTableRepository;//作品
    @Autowired
    TravelTableRepository travelTableRepository;

    @Override
    public XaResult<CommentVo> findOne(Long tId) throws BusinessException {
        throw new BusinessException(XaConstant.Message.error_method_no_impl);
    }

    @Override
    public XaResult<Page<CommentVo>> findListNEStatusByFilterPage(Integer status, Map<String, Object> filterParams, Pageable pageable) throws BusinessException {
        //住(机构)
        if (NumberUtils.toLong(filterParams.get("EQ_commentTypes")+"", 0)  == JConstant.Order_CommentType.HOURSE) {
            long institutionId = Long.parseLong(filterParams.get("EQ_objectId")+"");
            List<InsHotelRoomsTable> insRooms = insHotelRoomsTableRepository.findByInstitutionId(institutionId);
            if (XaUtil.isNotEmpty(insRooms)) {
                Set<Long> roomIdSet = com.web.webstart.base.util.CollectionUtils.subCollectionSet(insRooms, "id");
                filterParams.remove("EQ_objectId");
                filterParams.put("IN_objectId", JSON.toJSON(roomIdSet));
            }
        }

        Map<String, SearchFilter> filters = SearchFilter.parse(filterParams);
        if (status == null) {// 默认显示非删除的所有数据
            status = XaConstant.Status.delete;
        }
        filters.put("status", new SearchFilter("status", Operator.NE, status));


        Page<Comment> page = commentRepository.findAll(DynamicSpecifications
                .bySearchFilter(filters.values(), Comment.class), pageable);
        XaResult<Page<CommentVo>> xr = new XaResult<>();
        xr.setObject(new MyPage<>(page, JSON.parseArray(JSON.toJSONString(page.getContent()), CommentVo.class)));
        for (int i = 0; i < page.getContent().size(); i++) {
            xr.getObject().getContent().get(i).setId(page.getContent().get(i).getId());
        }

        //拼装用户信息
        if (XaUtil.isNotEmpty(page) && XaUtil.isNotEmpty(page.getContent())) {
            Set<String> set = com.web.webstart.base.util.CollectionUtils.subCollectionSet(page.getContent(), "userId");
            Set<Long> setLong = (Set<Long>) com.web.webstart.base.util.CollectionUtils.transformedCollectionForNumber(set, Long.class);
            Iterable<User> users = userRepository.findAll(setLong);
            Map<Long, User> map = com.web.webstart.base.util.CollectionUtils.listToMap(users.iterator(), new Function<User, Long>() {
                @Override
                public Long apply(User user) {
                    return user.getId();
                }
            });
            for (int j = 0; j < xr.getObject().getContent().size(); ++j) {
                Long userId = Long.parseLong(page.getContent().get(j).getUserId());
                User user = map.get(userId);
                xr.getObject().getContent().get(j).setUserVo(JSON.parseObject(JSON.toJSONString(user), UserVo.class));
            }
        }
        return xr;
    }

    @Override
    public XaResult<List<CommentVo>> findListEQStatusByFilter(
            Integer status, Map<String, Object> filterParams, Pageable pageable)
            throws BusinessException {
        throw new BusinessException(XaConstant.Message.error_method_no_impl);
    }

    @Override
    public XaResult<CommentVo> multiOperate(String modelIds,
                                            Integer status) throws BusinessException {
        XaResult<CommentVo> xr = new XaResult<CommentVo>();
        if (status == null) {
            status = XaConstant.Status.delete;
        }
        if (modelIds != null) {
            String[] ids = modelIds.split(",");
            for (String id : ids) {
                Comment obj = commentRepository.findByIdAndStatusNot(Long.parseLong(id), status);
                if (XaUtil.isNotEmpty(obj)) {
                    obj.setStatus(status);
                    obj = commentRepository.save(obj);
                    xr.setObject(JSON.parseObject(JSON.toJSONString(obj), CommentVo.class));
                    xr.getObject().setId(obj.getId());
                }
            }
        }
        LOGGER.info("更改数据状态----->Comment");
        return xr;
    }

    //删除评论
    @Override
    public XaResult<CommentVo> deleteCommentById(Long commontId, Long userId)
            throws BusinessException {
        XaResult<CommentVo> xr = new XaResult<CommentVo>();
        Comment obj = commentRepository.findByIdAndStatusNot(commontId, XaConstant.Status.delete);
        if (XaUtil.isEmpty(obj)) {
            xr.error(XaConstant.Message.object_property_not_find);
            return xr;
        }
        if (userId != Long.parseLong(obj.getUserId())) {
            xr.error("只能删除自己的评论!");
            return xr;
        }
        obj.setStatus(XaConstant.Status.delete);
        obj = commentRepository.save(obj);
        xr.setObject(JSON.parseObject(JSON.toJSONString(obj), CommentVo.class));
        xr.getObject().setId(obj.getId());
        return xr;
    }

    @Override
    public XaResult<CommentVo> saveComment(Comment model) throws Exception {
        XaResult<CommentVo> xr = new XaResult<CommentVo>();

        //只有待评论状态的,可以评论
        long orderDetailId = Long.parseLong(model.getOrderDetailId());
        OrderDetail orderDetail = orderDetailRepository.findById(orderDetailId);
        if (XaUtil.isEmpty(orderDetail)) {
            throw new BusinessException("orderDetailId不存在(" + model.getId() + ")");
        }
        if (orderDetail.getComm() != null && orderDetail.getComm()) {
            throw new BusinessException("该商品您已经评价,请不要重复评价!");
        }
        String orderNo = orderDetail.getOrderNo();
        Order order = orderRepository.findByOrderNo(orderNo);
        if (XaUtil.isEmpty(order)) {
            throw new BusinessException("订单信息不存在(" + orderDetail.getOrderNo() + ")!");
        }
        if (Long.parseLong(order.getOrderState()) != JConstant.OrderStatus.UN_COMMENT) {
            throw new BusinessException("只有待评价的订单才允许评价(" + order.getOrderNo() + ")");
        }
        if (order.getUserId() != Long.parseLong(model.getUserId())) {
            throw new BusinessException("userId和orderDetailId不匹配(userId=" + model.getUserId() + ";orderNo=" + orderDetail.getOrderNo() + ";orderDetailId=" + model.getOrderDetailId() + ")!");
        }
        model.setObjectId(orderDetail.getShop_ProductSPU());
        if (model.getCommentTypes() != NumberUtils.toInt(order.getOrderType(),0)) {
            throw new ValidationException(XaConstant.Code.code_validation_failure, "评论类型和订单类型不匹配，请检查commentTypes!");
        }

        //评论
        int orderType = NumberUtils.toInt(order.getOrderType());
        String commentName = "";
        String commentUrl = "";
        switch (orderType) {
            case JConstant.Order_CommentType.SERVICE_NURSE_TRANING: {
                ServiceNurseTraining en = nurseTrainingRepository.findByIdAndStatusNot(Long.valueOf(model.getObjectId()), XaConstant.Status.delete);
                if (XaUtil.isNotEmpty(en)) {
                    commentName = en.getNurseTraining_Name();
                    commentUrl = en.getNurseTraining_url();
                }
            }
            break;
            case JConstant.Order_CommentType.INSTIBUTION_VISITING: {
                Institution en = institutionRepository.findByIdAndStatusNot(Long.valueOf(model.getObjectId()), XaConstant.Status.delete);
                if (XaUtil.isNotEmpty(en)) {
                    commentName = en.getInstitution_Name();
                    commentUrl = en.getInstitution_pic();
                }
            }
            break;
            case JConstant.Order_CommentType.HOURSE: {
                InsHotelRoomsTable en = insHotelRoomsTableRepository.findByIdAndStatusNot(Long.valueOf(model.getObjectId()), XaConstant.Status.delete);
                if (XaUtil.isNotEmpty(en)) {
                    commentName = en.getHotelRooms_Name();
                    List<Banner> banner = bannerRepository.findByobjectIdAndTypeAndStatusNot(Long.valueOf(model.getObjectId()), JConstant.BannerType.INSTITUTION_HOURSE, XaConstant.Status.delete);
                    if (XaUtil.isNotEmpty(banner)) {
                        commentUrl = banner.get(0).getPicurl();
                    }
                }
            }
            break;
            case JConstant.Order_CommentType.GOODS: {
                Shop en = shopRepository.findById(Long.valueOf(model.getObjectId()));
                if (XaUtil.isNotEmpty(en)) {
                    commentName = en.getShopProductName();
                    if (XaUtil.isNotEmpty(en.getShopProductPicUrls())) {
                        commentUrl = en.getShopProductPicUrls().split(JConstant.SYMBOL_DOT)[0];
                    }
                }
            }
            case JConstant.Order_CommentType.GOODS_EXCHANGE: {
                ExchangeProducts en = exchangeProductsRepository.findByIdAndStatusNot(Long.valueOf(model.getObjectId()), XaConstant.Status.delete);
                if (XaUtil.isNotEmpty(en)) {
                    commentName = en.getProductName();
                    commentUrl = en.getProductImg();
                }
            }
            break;
            case JConstant.Order_CommentType.ARTWORK: {
                AutherWorksTable en = autherWorksTableRepository.findByIdAndStatusNot(Long.valueOf(model.getObjectId()), XaConstant.Status.delete);
                if (XaUtil.isNotEmpty(en)) {
                    commentName = en.getWorksName();
                    if (XaUtil.isNotEmpty(en.getWorksImgs())) {
                        commentUrl = en.getWorksImgs().split(JConstant.SYMBOL_DOT)[0];
                    }
                }
            }
            break;
            case JConstant.Order_CommentType.TOUR: {
                TravelTable en = travelTableRepository.findByIdAndStatusNot(Long.valueOf(model.getObjectId()), XaConstant.Status.delete);
                if (XaUtil.isNotEmpty(en)) {
                    commentName = en.getTravelItemName();
                    List<Banner> banners = bannerRepository.findByobjectIdAndTypeAndStatusNot(Long.valueOf(model.getObjectId()), JConstant.BannerType.TRAVEL, XaConstant.Status.delete);
                    if (XaUtil.isNotEmpty(banners)) {
                        commentUrl = banners.get(0).getPicurl();
                    }
                }
            }
            break;
        }
        try {
            int lenght = ReflectionUtils.getHibernateColumnAnnotationLength(Comment.class, "commentName");
            model.setCommentName(commentName.length() > lenght ? commentName.substring(0, lenght) : commentName);
            model.setCommentUrl(commentUrl);
            model.setObjectId(orderDetail.getShop_ProductSPU());
        } catch (Exception e) {
            e.printStackTrace();
            throw new BusinessException(e.getLocalizedMessage());
        }

        Comment obj = commentRepository.save(model);
        xr.setObject(JSON.parseObject(JSON.toJSONString(obj), CommentVo.class));
        xr.getObject().setId(obj.getId());


        //订单,修改订单状态
        List<OrderDetail> orderDetails = orderDetailRepository.findByOrderNoAndStatusNot(orderNo, XaConstant.Status.delete);
        OrderDetail ooo = null;
        //订单详情变成已经评论
        if (XaUtil.isNotEmpty(orderDetails)) {
            Map<Long, OrderDetail> map = com.web.webstart.base.util.CollectionUtils.listToMap(orderDetails.iterator(), new Function<OrderDetail, Long>() {
                @Override
                public Long apply(OrderDetail orderDetail) {
                    return orderDetail.getId();
                }
            });
            ooo = map.get(orderDetailId);
            ooo.setComm(true);
            ooo = orderDetailRepository.save(ooo);
        }

        LOGGER.info("新增数据成功----->Comment" + orderDetailId + " " + XaUtil.getBool(ooo.getComm()));
        boolean isAllComm = true;
        orderDetails = orderDetailRepository.findByOrderNoAndStatusNot(orderNo, XaConstant.Status.delete);//重新查询一次
        List<Boolean> booleanList = com.web.webstart.base.util.CollectionUtils.subCollection(orderDetails, "comm");
        for (int j = 0; booleanList != null && j < booleanList.size(); ++j) {
            if (BooleanUtils.isFalse(booleanList.get(j))) {
                isAllComm = false;
            }
        }

        OrderVo tempOrder = null;
        if (isAllComm) {
            //修改订单状态为已评论
            OrderVo orderVo = orderService.findOrderInfoByOrderNo(orderNo).getObject();
            orderVo.setOrderState(JConstant.OrderStatus.SUCCES_TRADE + "");
            orderVo.setOrder_Sucess_DateTime(DateUtils.getToDayStr());
            tempOrder = orderService.updateModel(JSON.parseObject(JSON.toJSONString(orderVo), Order.class)).getObject();
        }
        return xr;
    }

    @Override
    public XaResult<List<CommentVo>> findListNEStatusByFilter(
            Integer status, Map<String, Object> filterParams, Pageable pageable)
            throws BusinessException {
        Map<String, SearchFilter> filters = SearchFilter.parse(filterParams);
        if (status == null) {// 默认显示非删除的所有数据
            status = XaConstant.Status.delete;
        }
        filters.put("status", new SearchFilter("status", Operator.NE, status));
        Page<Comment> page = commentRepository.findAll(DynamicSpecifications
                .bySearchFilter(filters.values(), Comment.class), pageable);
        XaResult<List<CommentVo>> xr = new XaResult<List<CommentVo>>();
        xr.setObject(JSON.parseArray(JSON.toJSONString(page.getContent()), CommentVo.class));
        for (int i = 0; i < page.getContent().size(); i++) {
            xr.getObject().get(i).setId(page.getContent().get(i).getId());
        }
        return xr;
    }


    /**
     * 查询指定的酒店(机构)的评论
     * 酒店type type {@link com.web.exiaodao.business.constant.JConstant.Order_CommentType HOURSE}
     *
     * @param institutionId 机构的id 不能是null
     * @param userId        用户id 可以为null
     * @param pageable      分页 不能为null
     * @return
     * @throws BusinessException
     * @author duandazhi
     * @date 2017/1/2 下午6:29
     */
    @Override
    public XaResult<List<CommentVo>> findInstitutionCommonts(Long institutionId, Long userId, Pageable pageable)
            throws BusinessException {
        XaResult<List<CommentVo>> xr = new XaResult<>();
        try {
            Objects.requireNonNull(institutionId);
            //1:根据机构id查找所有房子的id
            List<InsHotelRoomsTable> insRooms = insHotelRoomsTableRepository.findByInstitutionIdAndStatusNot(institutionId, XaConstant.Status.delete);
            if (XaUtil.isNotEmpty(insRooms)) {
                Set<Long> roomIdSet = com.web.webstart.base.util.CollectionUtils.subCollectionSet(insRooms, "id");
                Map<String, Object> filterParams = null;
                if (XaUtil.isNotEmpty(userId)) {
                    filterParams =  WebUitl.getParametersStartingWith(
                            "{'search_IN_objectId':'"+  JSON.toJSONString(roomIdSet) +"'" +
                                    ",'search_NE_status':'"+ XaConstant.Status.delete+"'" +
                                    ",'search_EQ_commentTypes':'"+ JConstant.Order_CommentType.HOURSE+"'" +
                                    ",'search_EQ_userId':'"+userId+"'}", "search_");
                } else {
                    filterParams =  WebUitl.getParametersStartingWith(
                            "{'search_NE_status':'"+ XaConstant.Status.delete+"'" +
                                    ",'search_EQ_commentTypes':'"+ JConstant.Order_CommentType.HOURSE+"'" +
                                    ",'search_IN_objectId':'"+JSON.toJSONString(roomIdSet)+"'}", "search_");
                }
                return this.findListNEStatusByFilter(null, filterParams, pageable);
            }
            //2:搜索
        } catch (Exception e) {
            e.printStackTrace();
            xr.error(XaConstant.Message.error, true);
            throw new BusinessException(e.getLocalizedMessage(), e);
        }
        return xr;
    }


    @Override
    @Transactional(rollbackFor = Exception.class)
    public XaResult<CommentVo> createModel(Comment model)
            throws BusinessException {
        throw new BusinessException(XaConstant.Message.error_method_no_impl);
    }

    @Override
    public XaResult<CommentVo> updateModel(Comment model)
            throws BusinessException {
        throw new BusinessException(XaConstant.Message.error_method_no_impl);
    }

}
